package com.hm.ibsm.service;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;

import com.hm.common.def.ActivateDef;
import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageParam;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.EncryptUtil;
import com.hm.ibsm.domain.QUserDomain;
import com.hm.ibsm.domain.UserDomain;
import com.hm.ibsm.manage.service.UserService;
import com.hm.ibsm.manage.vo.user.UserDetailVo;
import com.hm.ibsm.manage.vo.user.UserVo;
import com.hm.ibsm.repositry.IUserRepository;
import com.hm.ibsm.util.BaseDomain;
import com.hm.ibsm.util.BeanUtil;
import com.hm.ibsm.util.R.DB;
import com.querydsl.core.types.dsl.BooleanExpression;

/**
 * @author shishun.wang
 * @date 下午5:07:28 2017年2月2日
 * @version 1.0
 * @describe
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

	@Autowired
	private IUserRepository userRepository;

	@PersistenceContext
	private EntityManager entityManager;

	@Override
	public void addUser(UserVo user) {
		if (CommonUtil.isAnyEmpty(user.getAccount(), user.getPwd())) {
			throw ServiceException.warn("账户名、密码不能为空");
		}

		if (CommonUtil.isNotEmpty(user.getUserName()) && CommonUtil.isNotEmpty(userRepository.findByUserName(user.getUserName(), ActivateDef.ENABLE))) {
			throw ServiceException.warn("用户名已存在");
		}

		if (CommonUtil.isNotEmpty(user.getEmail()) && CommonUtil.isNotEmpty(userRepository.findByEmail(user.getEmail(), ActivateDef.ENABLE))) {
			throw ServiceException.warn("该邮箱已注册");
		}

		if (CommonUtil.isNotEmpty(user.getMobile()) && CommonUtil.isNotEmpty(userRepository.findByMobile(user.getMobile(), ActivateDef.ENABLE))) {
			throw ServiceException.warn("该电话号码已注册");
		}

		UserDomain userDomain = new UserDomain();
		{
			String[] ignoreColumn = BaseDomain.ignoreColumn();
			BeanUtil.copyProperties(user, userDomain, ignoreColumn);
			userDomain.setPwd(EncryptUtil.Md5.getMD5Code(userDomain.getPwd()));
			userDomain.setActivate(ActivateDef.ENABLE);
		}
		userRepository.save(userDomain);
	}

	@Override
	public void updateUser(String userId, UserVo user) {
		UserDomain userDomain = userRepository.findOne(userId);
		checkUserExists(userDomain, userId);

		if (CommonUtil.isNotEmpty(user.getUserName())) {
			UserDomain domain = userRepository.findByUserName(user.getUserName(), ActivateDef.ENABLE);

			if (CommonUtil.isNotEmpty(domain) && !domain.getId().equals(userId)) {
				throw ServiceException.warn("用户名已存在");
			}
		}

		if (CommonUtil.isNotEmpty(user.getEmail())) {
			UserDomain domain = userRepository.findByEmail(user.getEmail(), ActivateDef.ENABLE);

			if (CommonUtil.isNotEmpty(domain) && !domain.getEmail().equals(user.getEmail())) {
				throw ServiceException.warn("该邮箱已注册");
			}
		}

		if (CommonUtil.isNotEmpty(user.getMobile())) {
			UserDomain domain = userRepository.findByMobile(user.getMobile(), ActivateDef.ENABLE);

			if (CommonUtil.isNotEmpty(domain) && !domain.getMobile().equals(user.getMobile())) {
				throw ServiceException.warn("该电话号码已注册");
			}
		}

		{
			String[] ignoreColumn = BaseDomain.ignoreColumn();
			{
				ignoreColumn[ignoreColumn.length] = "pwd";
				ignoreColumn[ignoreColumn.length + 1] = "privateKey";
				ignoreColumn[ignoreColumn.length + 2] = "privateKey";
			}
			BeanUtil.copyProperties(user, userDomain, ignoreColumn);
		}
		userRepository.save(userDomain);
	}

	@Override
	public void deleteUser(String userId) {
		UserDomain userDomain = userRepository.findOne(userId);
		checkUserExists(userDomain, userId);
		userDomain.setStatus(DataStatusDef.DISABLE);
		userDomain.setActivate(ActivateDef.DISABLE);
		userRepository.save(userDomain);
	}

	@Override
	public UserDetailVo getUserByMobile(String mobile) {
		UserDomain userDomain = userRepository.findByMobile(mobile, ActivateDef.ENABLE);
		return buildUserDetail(mobile, userDomain);
	}

	@Override
	public UserDetailVo getUserByEmail(String email) {
		UserDomain userDomain = userRepository.findByEmail(email, ActivateDef.ENABLE);
		return buildUserDetail(email, userDomain);
	}

	@Override
	public UserDetailVo getUserByAccount(String account) {
		UserDomain userDomain = userRepository.findByAccount(account, ActivateDef.ENABLE);
		return buildUserDetail(account, userDomain);
	}

	@Override
	public UserDetailVo getUserDetail(String userId) {
		UserDomain userDomain = userRepository.findOne(userId);
		checkUserExists(userDomain, userId);

		UserDetailVo userDetailVo = new UserDetailVo();
		BeanUtil.copyProperties(userDetailVo, userDomain);
		return userDetailVo;
	}

	@Override
	public PageInfo<UserVo> query(PageParam page, String userName, String account, String email, String mobile) {
		PageRequest pageable = new PageRequest(page.getPage(), page.getSize(), new Sort(Direction.DESC, new String[] { DB.DEFAULT_SORT }));
		QUserDomain qUserDomain = QUserDomain.userDomain;
		BooleanExpression predicate = qUserDomain.status.eq(DataStatusDef.ENABLE);
		{
			if (CommonUtil.isNotEmpty(userName)) {
				predicate.and(qUserDomain.userName.like(userName));

			}
			if (CommonUtil.isNotEmpty(account)) {
				predicate.and(qUserDomain.account.like(account));
			}
			if (CommonUtil.isNotEmpty(email)) {
				predicate.and(qUserDomain.email.eq(email));
			}
			if (CommonUtil.isNotEmpty(mobile)) {
				predicate.and(qUserDomain.mobile.eq(mobile));
			}
		}
		Page<UserDomain> pageContent = userRepository.findAll(predicate, pageable);

		List<UserVo> vos = new ArrayList<UserVo>();
		pageContent.getContent().stream().forEach(user -> {
			UserVo vo = new UserVo();
			BeanUtil.copyProperties(user, vo);
			vos.add(vo);
		});

		return new PageInfo<UserVo>(vos, pageContent.getTotalPages(), pageContent.getTotalElements());
	}

	private UserDetailVo buildUserDetail(Object queryParam, UserDomain userDomain) {
		checkUserExists(userDomain, queryParam);

		UserDetailVo userDetailVo = new UserDetailVo();
		BeanUtil.copyProperties(userDomain, userDetailVo);
		return userDetailVo;
	}

	private void checkUserExists(UserDomain userDomain, Object queryParam) {
		if (CommonUtil.isEmpty(userDomain)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND, queryParam);
		}
	}

}
